from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel, Field, validator


class NetInterface(BaseModel):
    host: str = Field(title="ip地址")
    port: int = Field(title="网络端口")


class SerialInterface(BaseModel):
    com: str = Field(title="串口号")
    baud: int = Field(title="波特率")
    stopBit: int = Field(title="停止位")
    dataBit: int = Field(title="数据位")
    parity: int = Field(title="校验位")


class DeviceInSchema(BaseModel):
    no: str = Field(title="设备资产编号")
    name: str = Field(title="设备名称")
    disabled: Optional[bool] = Field(default=False, title="设备是否禁用")
    interface: NetInterface | SerialInterface = Field(title="设备可通讯接口")
    communicationId: str = Field(title="通讯协议id")

    @validator("no", "name")
    def removeBlankString(cls, value):
        return value.strip() if isinstance(value, str) else value


class DeviceOutSchema(BaseModel):
    no: str = Field(title="设备资产编号")
    name: str = Field(title="设备名称")
    disabled: bool = Field(title="设备是否禁用")


class DeviceDetailSchema(DeviceOutSchema):
    remark: Optional[str] = Field(default="", title="备注信息")
    interface: NetInterface | SerialInterface = Field(title="设备可通讯接口")
    communicationId: str = Field(title="通讯协议id")


class DeviceModifySchema(BaseModel):
    no: Optional[str] = Field(default=None, title="设备资产编号")
    name: Optional[str] = Field(default=None, title="设备名称")
    disabled: Optional[bool] = Field(default=None, title="设备是否禁用")
    interface: Optional[NetInterface | SerialInterface] = Field(default=None, title="设备可通讯接口")
    communicationId: Optional[str] = Field(default=None, title="通讯协议id")


class PointSchema(BaseModel):
    name: str = Field(default=..., title="点位名称")
    group: str = Field(default=..., title="点位分组名称")
    func: str = Field(default=..., title="功能码")
    addr: str | int = Field(default=..., title="点位地址")
    desc: Optional[str] = Field(default=None, title="点位相关描述信息")


class PointInSchema(BaseModel):
    name: str = Field(default=..., title="点位名称")
    func: str = Field(default=..., title="功能码")
    addr: str | int = Field(default=..., title="点位地址")
    desc: Optional[str] = Field(default=None, title="点位相关描述信息")

    @validator("name", "func", "desc")
    def removeBlankString(cls, value):
        return value.strip() if isinstance(value, str) else value

    @validator("addr")
    def addrValidate(cls, v: str, values: dict):
        if not v:
            raise ValueError("地址不允许为空")
        if not isinstance(v, str):
            v = str(v)
        if values["func"].upper() in ("M", "X", "Y"):
            return int(v, 16)
        else:
            return int(v, 10)


class PointUpdateSchema(BaseModel):
    deviceNo: Optional[str] = Field(default=None, title="所属设备资产编号")
    group: Optional[str] = Field(default=None, title="所属分组名称")
    name: Optional[str] = Field(default=None, title="点位名称")
    func: Optional[str] = Field(default=None, title="功能码")
    addr: Optional[str] = Field(default=None, title="点位地址")
    desc: Optional[str] = Field(default=None, title="点位相关描述信息")

    @validator("deviceNo", "group", "name", "func", "desc")
    def removeBlankString(cls, value):
        return value.strip() if isinstance(value, str) else value

    @validator("addr")
    def addrValidate(cls, v: str, values: dict):
        if not v or not isinstance(v, str):
            return v
        if values["func"].upper() in ("M", "X", "Y"):
            return int(v, 16)
        else:
            return int(v, 10)


class PointOutSchema(BaseModel):
    id: int = Field(title="点位索引")
    name: str = Field(title="点位名称")
    deviceNo: str = Field(title="所属设备资产编号")
    group: str = Field(title="所属分组名称")
    func: str = Field(title="功能码")
    addr: str | int = Field(title="点位地址")
    desc: Optional[str] = Field(default=None, title="点位相关描述信息")

    @validator("addr")
    def addrValidate(cls, v: int, values: dict):
        if isinstance(v, str):
            return v
        if values["func"].upper() in ("M", "X", "Y"):
            return "{:X}".format(v)
        else:
            return str(v)


class DeviceStatusSchema(BaseModel):
    no: str = Field(title="设备编号")
    disabled: bool = Field(title="设备是否禁用")


class CheckInPoint(BaseModel):
    group: Optional[Any] = Field(default=None, title="所属分组名称")
    name: Optional[Any] = Field(default=None, title="点位名称")
    func: Optional[Any] = Field(default=None, title="功能码")
    addr: Optional[Any] = Field(default=None, title="点位地址")
    desc: Optional[Any] = Field(default=None, title="点位相关描述信息")


class CheckItemInSchema(BaseModel):
    deviceNo: Optional[str] = Field(title="设备编号")
    points: list[CheckInPoint] = Field(title="点位列表")


class CheckResultItem(BaseModel):
    value: Optional[str] = Field(default=None, title="校验值")
    level: Optional[int] = Field(default=0, title="错误等级 0-正常 1-警告 2-错误")
    tip: Optional[str] = Field(default=None, title="错误提示")


class CheckOutPoint(BaseModel):
    group: Optional[CheckResultItem] = Field(default=None, title="所属分组名称")
    name: Optional[CheckResultItem] = Field(default=None, title="点位名称")
    func: Optional[CheckResultItem] = Field(default=None, title="功能码")
    addr: Optional[CheckResultItem] = Field(default=None, title="点位地址")
    desc: Optional[CheckResultItem] = Field(default=None, title="点位相关描述信息")


class CheckOutItemSchema(BaseModel):
    deviceNo: Optional[CheckResultItem] = Field(default=None, title="设备编号")
    points: list[CheckOutPoint] = Field(default=[], title="点位列表")


class CheckSuccessPoint(PointInSchema):
    deviceNo: str = Field(title="所属设备编号")
    group: str = Field(title="所属分组名称")


class CheckFailPoint(BaseModel):
    deviceNo: Optional[Any] = Field(default=None, title="所属设备编号")
    group: Optional[Any] = Field(default=None, title="所属分组名称")
    name: Optional[Any] = Field(default=None, title="点位名称")
    func: Optional[Any] = Field(default=None, title="功能码")
    addr: Optional[Any] = Field(default=None, title="点位地址")
    desc: Optional[Any] = Field(default=None, title="点位相关描述信息")


class BatchInputResult(BaseModel):
    count: int = Field(default=0, title="总条目数")
    successCount: int = Field(default=0, title="插入成功条目数")
    failCount: int = Field(default=0, title="插入失败条目数")
    failList: Optional[list[CheckFailPoint]] = Field(default=[], title="插入失败的数据")
    successList: Optional[list[CheckSuccessPoint]] = Field(default=[], title="插入成功的数据")


class RTDeviceInSchema(BaseModel):
    devices: list[str] = Field(title="设备资产编号列表")
    logDev: Optional[str] = Field(default=None, title="用户需要查看日志的设备编号")


class RTLog(BaseModel):
    time: str = Field(title="异常发生时间")
    content: str = Field(title="异常内容")


class RTDeviceOutSchema(BaseModel):
    status: dict[str, int] = Field(default={}, title="设备连接状态", description="1-正常连接 2-部分点位异常 3-通讯失败")
    logs: Optional[list[RTLog]] = Field(default=[], title="目标设备的异常日志")


class RTPointInSchema(BaseModel):
    no: str = Field(title="设备资产编号")
    groups: list[str] = Field(title="需要访问的分组")


class RTPointOutSchema(BaseModel):
    no: str = Field(title="设备资产编号")
    connectStatus: int = Field(default=0, title="设备连接状态", description="1-正常连接 2-部分点位异常 3-通讯失败")
    groups: dict[str, dict[str, int | None] | None] | None = Field(default=None, title="分组点位表及其值")
